

using System;
using System.Xml;
using System.Text;
using System.IO;

namespace CUtil
{
	/// <summary>
	/// Logger class future implementation that will allow the writing of logging messages to the 
	/// registry or an xml file will be implementated for Log Viewer ( Part of Researcher and NN )
	/// </summary>
	public class Logger
	{
		private bool bLogToEventViewer;
		private bool bLogToXMLFile;
		private bool bUseTimeStamp;
		private string strFileName;
		private SimpleEventLog simpleEventLog;

		private XmlTextWriter xmlWriter;

		private bool bUseEventLog;
		private bool bUseXMLFile;

		/// <summary>
		/// log to the event viewer
		/// </summary>
		public bool LogToEventViewer
		{
			get
			{
				return bLogToEventViewer;
			}
			set
			{
				bLogToEventViewer = value;
			}
		}

		/// <summary>
		/// log to an xml file
		/// </summary>
		public bool LogToXMLFile 
		{
			get
			{
				return bLogToXMLFile;
			}
			set
			{
				bLogToXMLFile = value;
			}
		}

		/// <summary>
		/// use a time stamp on all messages
		/// </summary>
		public bool UseTimeStamp
		{
			get
			{
				return bUseTimeStamp;
			}
			set
			{
				bUseTimeStamp = value;
			}
		}


		/// <summary>
		/// Filename of the xml file to use
		/// </summary>
		public string FileName
		{
			get
			{
				return strFileName;
			}
			set
			{
				strFileName = value;
			}
		}

		/// <summary>
		/// get the current time
		/// </summary>
		public string TimeStamp
		{
			get
			{
				return DateTime.Now.ToLocalTime().ToString();
			}
		}

		/// <summary>
		/// default constructor
		/// </summary>
		public Logger()
		{
			//
			// TODO: Add constructor logic here
			//

			LogToEventViewer = false;
			LogToXMLFile = false;
			UseTimeStamp = false;
			bUseEventLog = false;
			bUseXMLFile = false;
		}


		/// <summary>
		/// constructor 
		/// </summary>
		/// <param name="eventLogName">name of the event log</param>
		/// <param name="clearEventLog">clear the event log on startup</param>
		/// <param name="xmlFileName">name of the xml file to write to</param>
		/// <param name="documentName">name of the xml document</param>
		public Logger( string eventLogName, bool clearEventLog, string xmlFileName, string documentName )
		{
			if( eventLogName != null && eventLogName.Length > 0 )
			{
				simpleEventLog = new SimpleEventLog( eventLogName, clearEventLog );
				bUseEventLog = true;
			}

			if( xmlFileName != null && xmlFileName.Length > 0 )
			{
				FileName = xmlFileName;
				xmlWriter = new XmlTextWriter( FileName, System.Text.Encoding.UTF8 );
				xmlWriter.WriteStartDocument();
				xmlWriter.WriteStartElement( documentName );
				bUseXMLFile = true;
				UseTimeStamp = false;
			}
		}



		/// <summary>
		/// constructor with timestamp
		/// </summary>
		/// <param name="eventLogName">name of the event log</param>
		/// <param name="clearEventLog">clear the event log on startup</param>
		/// <param name="xmlFileName">name of the xml file to write to</param>
		/// <param name="documentName">name of the xml document</param>
		/// <param name="useTimeStamp">true to add a timestamp to each message</param>
		public Logger( string eventLogName, bool clearEventLog, string xmlFileName, string documentName, bool useTimeStamp ) 
			: this( eventLogName, clearEventLog, xmlFileName, documentName )
		{
			UseTimeStamp = useTimeStamp;
		}


		/// <summary>
		/// constructor for just using the event log
		/// </summary>
		/// <param name="eventLogName">name of the event Log</param>
		/// <param name="clearEventLog">clear the event log on startup</param>
		public Logger( string eventLogName, bool clearEventLog )
		{
			if( eventLogName != null && eventLogName.Length > 0 )
			{
				simpleEventLog = new SimpleEventLog( eventLogName, clearEventLog );
				bUseEventLog = true;
				bUseXMLFile = false;
				UseTimeStamp = false;
			}
		}

		/// <summary>
		/// constructor for just using the xml file
		/// </summary>
		/// <param name="xmlFileName">xml file to name</param>
		/// <param name="documentName">name of the xml document</param>
		public Logger( string xmlFileName, string documentName )
		{
			if( xmlFileName != null && xmlFileName.Length > 0 )
			{
				FileName = xmlFileName;
				FileStream stream;  
				FileInfo info = new FileInfo( xmlFileName );
				if( info.Exists == true )
				{
					info.Delete();
					stream = new FileStream( xmlFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 8, true );
					xmlWriter = new XmlTextWriter( stream, System.Text.Encoding.UTF8 );

				}
				else
				{
					stream = new FileStream( xmlFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, 8, true );
					xmlWriter = new XmlTextWriter( stream, System.Text.Encoding.UTF8 );
				}

				xmlWriter.WriteStartDocument();
				xmlWriter.WriteStartElement( documentName );
	
				bUseXMLFile = true;
				bUseEventLog = false;
				UseTimeStamp = false;
			}
		}

		/// <summary>
		/// constructor for event log with timestamp 
		/// </summary>
		/// <param name="eventLogName">name of the event log</param>
		/// <param name="clearEventLog">true to clear the event log on start up</param>
		/// <param name="useTimeStamp">use a timestamp in each message</param>
		public Logger( string eventLogName, bool clearEventLog, bool useTimeStamp ) : this( eventLogName, clearEventLog )
		{
			UseTimeStamp = useTimeStamp;
		}


		/// <summary>
		/// constructor for xml file using time stamp
		/// </summary>
		/// <param name="xmlFileName">name of the xml file</param>
		/// <param name="documentName">document name for the xml file</param>
		/// <param name="useTimeStamp">use a time stamp in each message</param>
		public Logger( string xmlFileName, string documentName, bool useTimeStamp ) : this( xmlFileName, documentName )
		{
			UseTimeStamp = useTimeStamp;
		}


		/// <summary>
		/// copy constructor
		/// </summary>
		/// <param name="log"></param>
		public Logger( Logger log )
		{
			this.LogToEventViewer = log.LogToEventViewer;
			this.LogToXMLFile = log.LogToXMLFile;
			this.FileName = log.FileName;
			this.UseTimeStamp = log.UseTimeStamp;
			this.xmlWriter = log.xmlWriter;
		}


		/// <summary>
		/// destructor
		/// </summary>
		~Logger()
		{
			try
			{
				if( xmlWriter != null )
					xmlWriter.Close();
			}
			catch( ObjectDisposedException )
			{
				
			}
		}


		/// <summary>
		/// close the logger
		/// </summary>
		public void Close()
		{
			if( bUseEventLog == true )
			{
				simpleEventLog.Close();
			}

			if( bUseXMLFile == true )
			{
				xmlWriter.Flush();
				xmlWriter.WriteEndElement();
				xmlWriter.WriteEndDocument();
				xmlWriter.Close();
			}
		}

		/// <summary>
		/// write an xml message
		/// </summary>
		/// <param name="dblPriority">priority level</param>
		/// <param name="message">error message</param>
		/// <param name="type">type ie node name</param>
		private void WriteXML( DebugLevelSet dblPriority, string message, string type )
		{
			StringBuilder strString = new StringBuilder();
			if( UseTimeStamp == true )
			{
				strString.Append( TimeStamp + " " );
			}

			strString.Append( message );

			xmlWriter.WriteStartElement( type );
			if( UseTimeStamp == true )
			{
				xmlWriter.WriteElementString( "Time", TimeStamp );
			}

			xmlWriter.WriteElementString( "Priority", dblPriority.ToString() );
			xmlWriter.WriteElementString( "Message", strString.ToString() );

			xmlWriter.WriteEndElement();

		}

		/// <summary>
		/// write an event log message
		/// </summary>
		/// <param name="dblPriority">priority level</param>
		/// <param name="message">error message</param>
		private void WriteEventLog( DebugLevelSet dblPriority, string message )
		{
			StringBuilder strString = new StringBuilder();
			if( UseTimeStamp == true )
			{
				strString.Append( TimeStamp + " " );
			}

			strString.Append( message );

			switch( dblPriority )
			{
				case DebugLevelSet.All : simpleEventLog.WriteInformation( strString.ToString() ); break;
				case DebugLevelSet.Errors : simpleEventLog.WriteError( strString.ToString() ); break;
				case DebugLevelSet.WarningsAndErrors : simpleEventLog.WriteWarning( strString.ToString() ); break;
			}
		}

		/// <summary>
		/// log a message
		/// </summary>
		/// <param name="dblPriority">debug level set priority</param>
		/// <param name="message">message to log</param>
		public void Log( DebugLevelSet dblPriority, string message )
		{

			lock( this )
			{
				/// probably wont use this for xml but allow it anyway
				if( bUseXMLFile == true )
				{
					WriteXML( dblPriority, message, dblPriority.ToString() );
				}

				if( dblPriority < DebugLevelSet.Warning && bUseEventLog == true )
				{
					WriteEventLog( dblPriority, message );
				}
			}
		}


		/// <summary>
		/// log a message
		/// </summary>
		/// <param name="dblPriority">debug level set priority</param>
		/// <param name="message">actual message to log</param>
		/// <param name="type">class or category name</param>
		public void Log( DebugLevelSet dblPriority, string message, string type )
		{
			lock( this )
			{
				if( bUseXMLFile == true )
				{
					WriteXML( dblPriority, message, type );
				}


				/// if higher or equal to warning can't log in event viewer
				if( dblPriority >= DebugLevelSet.Warning )
				{
					WriteEventLog( dblPriority, message );
				}
			}
		}

	}
}
